﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using ScrumTable.Common.Logging;

#endregion

namespace ScrumTable.Common
{


    /// <summary>
    /// Specifies utility functions which enhance the Enum class.
    /// </summary>
    public static class EnumUtil
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new dictionary of all name/value pairs of an enum.
        /// </summary>
        /// <typeparam name="T">Specifies the type of the enumeration to get the values from.</typeparam>
        /// <returns>Returns the newly created dictionary.</returns>
        public static IDictionary<string, object> ToDictionary<T>()
            where T : struct
        {
            Array rawEnumValues = Enum.GetValues(typeof(T));
            IDictionary<string, object> enumValues = new Dictionary<string, object>(rawEnumValues.Length);

            foreach (object rawValue in rawEnumValues)
            {
                enumValues[Enum.GetName(typeof(T), rawValue)] = rawValue;
            }
            return enumValues;
        }

        /// <summary>
        /// Converts the given input enum into an instance of the output
        /// enum. This method tries to convert by name and then by value.
        /// If both fails, the default output value is returned.
        /// </summary>
        /// <typeparam name="TIn">Specifies the type of the input enumeration.</typeparam>
        /// <typeparam name="TOut">Specifies the type of the output enumeration.</typeparam>
        /// <param name="source">Specifies the input enum value.</param>
        /// <returns>Returns the converted instance of an output enum value.</returns>
        public static TOut Convert<TIn, TOut>(TIn source)
            where TIn : struct
            where TOut : struct
        {
            IDictionary<string, object> outputMappings = ToDictionary<TOut>();
            IDictionary<string, object> inputMappings = ToDictionary<TIn>();
            string elementName = Enum.GetName(typeof(TIn), source);

            if (outputMappings.ContainsKey(elementName))
            {
                return (TOut)outputMappings[elementName];
            }
            else
            {
                object sourceValue = inputMappings[elementName];

                if (Enum.IsDefined(typeof(TOut), sourceValue))
                {
                    return (TOut)Enum.ToObject(typeof(TOut), sourceValue);
                }
                else
                {
                    return default(TOut);
                }
            }
        }

        /// <summary>
        /// Tries to parse the given string. All exceptions during the parse
        /// mechanism will be ignored and instead of that the default value
        /// is returned.
        /// </summary>
        /// <param name="toParse">Specifies the string to parse and convert into the given enum.</param>
        /// <param name="defaultValue">Specifies the default value to return, if an exception occurred.</param>
        public static T TryParse<T>(string toParse, T defaultValue)
            where T : struct
        {
            T resultValue;
            if (TryParse(toParse, out resultValue))
            {
                return resultValue;
            }
            return defaultValue;
        }

        /// <summary>
        /// Tries to parse the given string. All exceptions during the parse
        /// mechanism will be ignored and instead of that the default value
        /// is returned.
        /// </summary>
        /// <param name="toParse">Specifies the string to parse and convert into the given enum.</param>
        /// <param name="resultValue">Specifies the result value.</param>
        public static bool TryParse<T>(string toParse, out T resultValue)
            where T : struct
        {
            try
            {
                IDictionary<string, object> mappings = ToDictionary<T>();

                if (mappings.ContainsKey(toParse))
                {
                    resultValue = (T)Enum.ToObject(typeof(T), mappings[toParse]);
                    return true;
                }
            }
            catch (Exception e)
            {
                Logger.Debug(e.Message, e);
            }

            resultValue = default(T);
            return false;
        }

        /// <summary>
        /// Tries to parse the given string. All exceptions during the parse
        /// mechanism will be ignored and instead of that the default(T) value
        /// is returned.
        /// </summary>
        /// <param name="toParse">Specifies the string to parse and convert into the given enum.</param>
        public static T TryParse<T>(string toParse)
            where T : struct 
        {
            return TryParse(toParse, default(T));
        }

        #endregion
    }
}
